/*
 * Virtual Machine Manager Daemon
 * 24/04/2011 
 *
 * Adapted from original daemon skeleton by Peter Lombardo
 * 5/1/2006
 *
 */

/* Basic Daemon Structure
 *
 * Fork off the parent process
 * Change file mode mask (umask)
 * Open any logs for writing
 * Create a unique Session ID (SID)
 * Change the current working directory to a safe place
 * Close standard file descriptors
 * Enter actual daemon code
 */
 
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
 
#define DAEMON_NAME "vmmd"
#define PID_FILE    "/var/run/vmmd.pid"
 
/**************************************************************************
    Function: Print Usage
 
    Description:
        Output the command-line options for this daemon.
 
    Params:
        @argc - Standard argument count
        @argv - Standard argument array
 
    Returns:
        returns void always
**************************************************************************/
void PrintUsage(int argc, char *argv[]){
  if(argc >= 1) {
    printf("Usage %s [options]\n", argv[0]);
    printf("options: \n");
    printf("  -n don't fork off as a daemon\n");
    printf("  -h show this help screen\n");
  }
}
 
/**************************************************************************
    Function: signal_handler
 
    Description:
        This function handles select signals that the daemon may
        receive. This gives the daemon a chance to properly shut
        down in emergency situations. This function is installed
        as a signal handler in the 'main()' function.
 
    Params:
        @sig - The signal received
 
    Returns:
        returns void always
**************************************************************************/
void signal_handler(int sig) {
  switch(sig) {
    case SIGHUP:
    syslog(LOG_WARNING, "Received SIGHUP signal.");
    break;

    case SIGTERM:
    syslog(LOG_WARNING, "Received SIGTERM signal.");
    break;

    default:
    syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig));
    break;
  }
}


 
/**************************************************************************
    Function: main
 
    Description:
        The c standard 'main' entry point function.
 
    Params:
        @argc - count of command line arguments given on command line
        @argv - array of arguments given on command line
 
    Returns:
        returns integer which is passed back to the parent process
**************************************************************************/
int main(int argc, char *argv[]) {

  // By default we want to daemonize
  int daemonize = 1;
 
  // Setup signal handling before we start
  signal(SIGHUP,  signal_handler);
  signal(SIGTERM, signal_handler);
  signal(SIGINT,  signal_handler);
  signal(SIGQUIT, signal_handler);
 
  int c;
  // Process command line options
  while((c = getopt(argc, argv, "n|h")) != -1) {
    switch(c){
      case 'h':
      PrintUsage(argc, argv);
      exit(0);
      break;

      case 'n':
      daemonize = 0;
      printf("No-daemon mode selected...\n");
      break;

      // More options can be added here
      // ...

      default:
      PrintUsage(argc, argv);
      exit(0);
      break;
    }
  }
 
  // Setup syslog logging 
  openlog(DAEMON_NAME, LOG_CONS | LOG_PID, LOG_USER);
  syslog(LOG_INFO, "%s daemon starting up", DAEMON_NAME);
 
  /* Our process ID and Session ID */
  pid_t pid, sid;
 
  if(daemonize) {
    syslog(LOG_INFO, "starting the daemonizing process");
 
    /* Fork off the parent process */
    pid = fork();
    if(pid < 0) {
      exit(EXIT_FAILURE);
    }
    /* If we got a good PID, then
       we can exit the parent process. */
    if(pid > 0) {
      exit(EXIT_SUCCESS);
    }
 
    /* Change the file mode mask 
       By setting the umask to 0, we will have full
       access to the files generated by the daemon  */
    
    umask(0);
 
    /* Create a new SID for the child process 
       The child process must get a unique SID from the 
       kernel in order to operate, otherwise, the child 
       process becomes an orphan in the system */ 

    sid = setsid();
    if(sid < 0) {
      /* Log the failure */
      exit(EXIT_FAILURE);
    }
 
    /* Change the current working directory 
       The current working directory should be changed to 
       some place that is guaranteed to always be there  */
    
    if((chdir("/")) < 0) {
      /* Log the failure */
      exit(EXIT_FAILURE);
    }
 
    /* Close out the standard file descriptors
       Since a daemon cannot use the terminal, these file 
       descriptors are redundant and a potential security hazard */
    
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
  }
 
  /* The Big loop */
  int count = 1;
  while(1) {
    sleep(5);
    syslog(LOG_INFO ,"running the daemon for %d seconds", count++*5); 
  }

  syslog(LOG_INFO, "%s daemon exiting", DAEMON_NAME);
 
  //****************************************************
  // TODO: Free any allocated resources before exiting
  //****************************************************
 
  exit(0);
}
